#include <QCoreApplication>
#include <event2/event.h>
#include <event2/listener.h>
#include <iostream>
#include <signal.h>
#include <QDebug>
#include <stdio.h>
#include <unistd.h>
//正常的断开链接，超时会进入
void client_cb(int fd,short e,void* arg){
    event* ev = (event*)arg;
    //判断超时
    if(e & EV_TIMEOUT){
        qDebug() << "time out";
        event_free(ev);
        close(fd);
        return;
    }
    char buf[128] = {0};
    int len = recv(fd,buf,sizeof(buf) - 1,0);
    if(len > 0){
        qDebug() << buf;
        send(fd,"OK",2,0);
    }else{//此时需要清理这个event

        qDebug() << "event_free";
        event_free(ev);//函数内部会先调研event_del
        close(fd);
    }
}

void listen_cb(int fd,short e,void* arg){
    qDebug() << "listen_cb";
    sockaddr_in client;
    memset(&client,0,sizeof(client));
    socklen_t len = sizeof(client);
    int cfd = accept(fd,(sockaddr*)&client,&len);
    char ip[32] = {0};
    evutil_inet_ntop(AF_INET,&client.sin_addr,ip,sizeof(ip) - 1);
    qDebug() << "clent ip is" << ip;
    //客户端数据读取,传递这个事件本身，因为需要将这个事件删除
    event_base* base = (event_base*)arg;
    //水平触发
    //event* ev = event_new(base,cfd,EV_READ | EV_PERSIST,client_cb,event_self_cbarg());
    //边缘触发
    event* ev = event_new(base,cfd,EV_READ | EV_PERSIST | EV_ET,client_cb,event_self_cbarg());
    timeval ti = {10,0};
    event_add(ev,&ti);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    if(signal(SIGPIPE,SIG_IGN) == SIG_ERR){
        return -1;
    }

    evutil_socket_t sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock <= 0){
        perror("socket");
        return -1;
    }
    //设置端口复用和非阻塞
    evutil_make_listen_socket_reuseable(sock);
    evutil_make_socket_nonblocking(sock);
    sockaddr_in sin;
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(6666);
    int ret = ::bind(sock,(sockaddr*)&sin,sizeof(sin));
    if(ret)
        perror("bind");
    listen(sock,10);
    event_base* base = event_base_new();
    event* ev = event_new(base,sock,EV_READ|EV_PERSIST,listen_cb,base);
    event_add(ev,0);

    event_base_dispatch(base);
    return 0;
}
